發生在上個月一件非常不幸的事情, 在我興高采烈地
準備為我的 Minecraft 伺服器編寫一個菜單系統的時候,
不知為何, Termius 就將原本想寫的 'cd ./server'
自動補全為 'rm -rf ./server',
但最後還是有驚無險的恢復了 95% 以上的數據.
適用範圍#
- 文件仍然在快取中運行, 這也意味著在恢復期間,你不能結束該進程或關機.
步驟#
-
誤刪文件,但該文件被進程佔用.
$ rm test.sh
-
使用 lsof 命令列出已被刪除但仍被進程佔用的文件
$ lsof | grep -i delete | grep speed sh 6567 root 4r REG 253,0 865 /home/test.sh(deleted)
- 其中,第一項
sh
為進程名,第二項6567
為進程號
- 其中,第一項
-
進入進程目錄
$ cd /proc/6567/fd $ ls -la lr-x------. 1 root root 64 July 13 02:10 4 -> /home/test.sh (deleted)
- 其中,第九項
4
為文件描述符
- 其中,第九項
-
恢復
$ cat 4 > /home/test.sh
恢復一個文件夾#
-
若同時被刪除的是一個文件夾,則像這樣的手動恢復太過於繁瑣,特別是在小文件繁多的時候非常棘手,那麼,我們不妨使用一個小程序來進行批量的恢復.
-
在此之前,您需要把 步驟 1 中所有需要恢復的文件導出為一個 log 文件,這裡並不過多贅述.
use std::fs; use std::io::Read; fn main() { let mut log_file = fs::File::open("/home/deleted_files.log").unwrap(); // 填寫您待恢復的文件列表路徑 let mut logs = String::new(); log_file.read_to_string(&mut logs).unwrap(); let mut command = String::new(); let mut paths = Vec::new(); let logs = logs.split("\n"); for log in logs { let log = log.split_whitespace().collect::<Vec<&str>>(); if log.len() < 12 { continue; } let number = log[8]; // 8 為文件描述符所處列數, 根據文件實際情況進行修改 let path = log[10]; // 10 為文件原始路徑所在列數, 根據文件實際情況進行修改 if !path.starts_with("/home") { // 填寫您恢復至的目標文件夾 continue; } println!("{}: {}", number, path); command.push_str(format!("cat {} > ~/recovery{}\n", number, path).as_str()); let path = path.split("/").collect::<Vec<&str>>(); let path = path[..path.len() - 1].join("/"); let path = format!("~/recovery{}", path); if !paths.contains(&path) { paths.push(path); } } let mut complete_cmd = String::new(); for path in paths { complete_cmd.push_str(format!("mkdir -p {}\n", path).as_str()); } println!("{}", complete_cmd); complete_cmd.push_str(&command); fs::write("recovery.sh", complete_cmd).unwrap(); }
-
最後運行生成好的
recovery.sh
即可恢復全部文件.
注意: 對於 Minecraft 伺服器來說,玩家數據是無法直接恢復的,且本方法不能保證百分百找回全部被刪除的文件,還請各位及時做好文件備份,不要讓後悔成為誤刪的結果!
此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://blog.rescueme.life/posts/devops/restore-files-deleted-by-rm-but-occupied-by-processes